using Unity.Burst;
using Unity.Collections;
using Unity.Mathematics;
using Unity.Profiling;
using UnityEngine;
using UnityEngine.Jobs;

namespace Jobs.DOD
{
    [BurstCompile]
    struct WaveCubesJob : IJobParallelForTransform
    {
        [ReadOnly] public float ElapsedTime;

        public void Execute(int index, TransformAccess transform)
        {
            var distance = Vector3.Distance(transform.position, Vector3.zero);
            transform.localPosition += Vector3.up * math.sin(ElapsedTime * 3f + distance * 0.2f);
        }
    }

    /// <summary>
    /// WaveCubes（面向数据DOD版）
    /// </summary>
    public class WaveCubesWithJobs : MonoBehaviour
    {
        public GameObject CubeArchetype;
        [Range(10, 100)] public int RadiusX;
        [Range(10, 100)] public int RadiusZ;

        TransformAccessArray mTransformAccessArray;

        static readonly ProfilerMarker<int> mProfilerMaker =
            new ProfilerMarker<int>("WaveCubesWithJobs UpdateTransform", "Objects Count");

        void Start()
        {
            mTransformAccessArray = new TransformAccessArray(4 * RadiusX * RadiusZ);
            for (int z = -RadiusZ; z < RadiusZ; z++)
            {
                for (int x = -RadiusX; x < RadiusX; x++)
                {
                    //var cube = Instantiate(CubeArchetype, transform); //要使用并行更新Transform则不可设置父节点
                    var cube = Instantiate(CubeArchetype);
                    cube.transform.position = new Vector3(x * 1.1f, 0, z * 1.1f);
                    mTransformAccessArray.Add(cube.transform);
                }
            }
        }

        void Update()
        {
            using (mProfilerMaker.Auto(mTransformAccessArray.length))
            {
                var waveCubesJob = new WaveCubesJob()
                {
                    ElapsedTime = Time.time,
                };
                //开始调度
                var waveCubesJobHandle = waveCubesJob.Schedule(mTransformAccessArray);
                //同步结果到主线程
                waveCubesJobHandle.Complete();
            }
        }

        void OnDestroy()
        {
            mTransformAccessArray.Dispose();
        }
    }
}